home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1993 / Internet Info CD-ROM (Walnut Creek) (1993).iso / networking / terms / tipx / tip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-11  |  15.8 KB  |  885 lines

  1. char *tipx_rev = "x1.21";
  2. #define PATCHLEVEL 1
  3. /*
  4.  * Copyright (c) 1983 The Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms are permitted
  8.  * provided that the above copyright notice and this paragraph are
  9.  * duplicated in all such forms and that any documentation,
  10.  * advertising materials, and other materials related to such
  11.  * distribution and use acknowledge that the software was developed
  12.  * by the University of California, Berkeley.  The name of the
  13.  * University may not be used to endorse or promote products derived
  14.  * from this software without specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19. /*
  20.  * Modifications by Warren Tucker <wht%n4hgf.uucp@emory.mathcs.emory.edu>
  21.  * for eight-bit transparent pass through and file transfer protocols
  22.  * are unencumbered in any way. They are yours, ours, everybody's, nobody's.
  23.  */
  24. /*+:EDITS:*/
  25. /*:05-08-1990-15:05-wht@n4hgf-rawthru */
  26. /*:05-08-1990-15:00-wht@n4hgf-move tip.c original to tip-orig.c */
  27.  
  28. #ifndef lint
  29. char copyright[] =
  30. "@(#) Copyright(c) 1983 The Regents of the University of California.\n\
  31.  All rights reserved.\n";
  32. #endif /* not lint */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)tip.c 5.8 (Berkeley) 9/2/88 (mod by wht@n4hgf)";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * tip - UNIX link to other systems
  40.  *  tip [-psv] [-speed] system-name [data]
  41.  * or
  42.  *  cu phone-number [-s speed] [-l line] [-a acu]
  43.  */
  44. #include "tip.h"
  45.  
  46. /*
  47.  * Baud rate mapping table
  48.  */
  49. int bauds[] = 
  50. {
  51.     0,50,75,110,134,150,200,300,600,
  52.     1200,1800,2400,4800,9600,19200,38400,-1
  53. };
  54.  
  55. #ifdef TIPX
  56. int rawthru = 0;
  57. char *rawthru_msg = "\r\n--> raw tip:  3 ~ rapidly for ~ equivalent\r\n";
  58. char *no_rawthru_msg = "\r\n--> normal tip: 1 ~ == ~\r\n";
  59. extern char opened_tty[];
  60. #endif
  61.  
  62. int page;
  63. int disc = OTTYDISC;        /* tip normally runs this way */
  64. sigfunc_t    intprompt();
  65. sigfunc_t    timeout();
  66. sigfunc_t    cleanup();
  67. char *login();
  68. char *sname();
  69. char PNbuf[256];            /* This limits the size of a number */
  70. struct sgttyb ttyarg;
  71.  
  72. #ifdef TIPX
  73. typedef struct b_to_br
  74. {
  75.     char *baud_rate;
  76.     int B_code;
  77. } B_TO_BR;
  78.  
  79. B_TO_BR speeds[] =     /* ordered to put less common rates later in table */
  80. {                    /* and the vagaries of baud rates above 9600 "handled" */
  81.     "2400",    B2400,
  82.     "1200",    B1200,
  83.     "9600",    B9600,
  84. #if defined(B19200)
  85.     "19200",B19200,
  86. #endif
  87. #if defined(B38400)
  88.     "38400",B38400,
  89. #endif
  90.     "4800",    B4800,
  91.     "300",    B300,
  92.     "110",    B110,
  93.     "600",    B600,
  94.     "75",    B75,
  95.     "50",    B50,
  96.     "HUP",    B0,
  97.     "EXTA",    EXTA,
  98.     "EXTB",    EXTB,
  99.  
  100.     (char *)0,0
  101. };
  102. #endif /* TIPX */
  103.  
  104. /*+-------------------------------------------------------------------------
  105.     B_to_baud_rate(code) - convert CBAUD B_ code to baud rate string
  106. --------------------------------------------------------------------------*/
  107. #ifdef TIPX
  108. char *
  109. B_to_baud_rate(code)
  110. int code;
  111. {
  112. register int n;
  113.  
  114.     for(n=0; speeds[n].baud_rate; n++)
  115.         if(speeds[n].B_code == code)
  116.             return(speeds[n].baud_rate);
  117.     return("-----");
  118. }    /* end of B_to_baud_rate */
  119. #endif /* TIPX */
  120.  
  121. main(argc,argv)
  122. char *argv[];
  123. {
  124.     int uuid;
  125.     char *system = NOSTR;
  126.     char *data = NOSTR;
  127.     register int i;
  128.     register char *p;
  129.     char sbuf[12];
  130.  
  131.     uid = getuid();
  132.     gid = getgid();
  133.     euid = geteuid();    /* should be root */
  134.     egid = getegid();
  135.     uuid = getuucpuid();
  136.  
  137.     if(equal(sname(argv[0]),"cu"))
  138.     {
  139.         setreuid(uid,uuid);
  140.         cumode = 1;
  141.         cumain(argc,argv);
  142.         goto cucommon;
  143.     }
  144.  
  145.     if(argc < 2)
  146.     {
  147.         fprintf(stderr,"usage: tip [-psv] [-speed] [system-name] [data]\n");
  148.         exit(1);
  149.     }
  150.  
  151.     for(; argc > 1; argv++,argc--)
  152.     {
  153.         if(argv[1][0] != '-')
  154.         {
  155.             if(system)
  156.                 data = argv[1];
  157.             else
  158.                 system = argv[1];
  159.         }
  160.         else switch(argv[1][1])
  161.         {
  162.  
  163.         case 'p':
  164.             page++;
  165.             break;
  166.         case 's':
  167.             slip++;
  168.             break;
  169.         case 'v':
  170.             vflag++;
  171.             break;
  172.  
  173.         case '0':
  174.         case '1':
  175.         case '2':
  176.         case '3':
  177.         case '4':
  178.         case '5':
  179.         case '6':
  180.         case '7':
  181.         case '8':
  182.         case '9':
  183.             BR = atoi(&argv[1][1]);
  184.             break;
  185.  
  186.         default:
  187.             fprintf(stderr,"tip: %s, unknown option\n",argv[1]);
  188.             break;
  189.         }
  190.     }
  191.     if(!isatty(0) && !slip && !page)
  192.     {
  193.         fprintf(stderr,"tip: warning: input is not a tty\n");
  194.     }
  195.     if(slip)
  196.     {
  197.         setreuid(euid,uuid);
  198.         uid = 0;
  199.     }
  200.     else 
  201.     {
  202.         setreuid(uid,uuid);
  203.     }
  204.     euid = uuid;
  205.  
  206.     if(system == NOSTR)
  207.         goto notnumber;
  208.     if(isalpha(*system))
  209.         goto notnumber;
  210.     /*
  211.      * System name is really a phone number...
  212.      * Copy the number then stomp on the original (in case the number
  213.      *    is private, we don't want 'ps' or 'w' to find it).
  214.      */
  215.     if(strlen(system) > sizeof PNbuf - 1)
  216.     {
  217.         fprintf(stderr,"tip: phone number too long (max = %d bytes)\n",
  218.             sizeof PNbuf - 1);
  219.         exit(1);
  220.     }
  221.     strncpy( PNbuf,system,sizeof PNbuf - 1 );
  222.     for(p = system; *p; p++)
  223.         *p = '\0';
  224.     PN = PNbuf;
  225.     (void)sprintf(sbuf,"tip%d",BR);
  226.     system = sbuf;
  227.  
  228. notnumber:
  229.     signal(SIGINT,cleanup);
  230.     signal(SIGQUIT,cleanup);
  231.     signal(SIGHUP,cleanup);
  232.     signal(SIGTERM,cleanup);
  233.     signal(SIGPIPE,cleanup);
  234.  
  235.     if((i = hunt(system)) == 0)
  236.     {
  237.         printf("all ports busy\n");
  238.         exit(3);
  239.     }
  240.     if(i == -1)
  241.     {
  242.         printf("link down\n");
  243.         (void)uu_unlock(uucplock);
  244.         exit(3);
  245.     }
  246.     setbuf(stdout,NULL);
  247.     loginit();
  248.  
  249.     /*
  250.      * Kludge, their's no easy way to get the initialization
  251.      *   in the right order, so force it here
  252.      */
  253.     if((PH = getenv("PHONES")) == NOSTR)
  254.         PH = "/etc/phones";
  255.     vinit();                /* init variables */
  256.     setparity("none");            /* set the parity table */
  257.     if((i = speed(number(value(BAUDRATE)))) == NULL)
  258.     {
  259.         printf("tip: bad baud rate %d\n",number(value(BAUDRATE)));
  260.         (void)uu_unlock(uucplock);
  261.         exit(3);
  262.     }
  263.  
  264.     if(slip)
  265.     {
  266.         if(SA == NOSTR)
  267.         {
  268.             printf("tip: local addr not set\n");
  269.             uu_unlock(uucplock);
  270.             exit(3);
  271.         }
  272.         if(DA == NOSTR)
  273.         {
  274.             printf("tip: destination addr not set\n");
  275.             uu_unlock(uucplock);
  276.             exit(3);
  277.         }
  278.         if(SM == NOSTR)
  279.         {
  280.             printf("tip: slip netmask not set\n");
  281.             uu_unlock(uucplock);
  282.             exit(3);
  283.         }
  284.     }
  285.  
  286.     /*
  287.      * Now that we have the logfile and the ACU open
  288.      *  return to the real uid and gid.  These things will
  289.      *  be closed on exit.  Swap real and effective uid's
  290.      *  so we can get the original permissions back
  291.      *  for removing the uucp lock.
  292.      */
  293.     user_uid();    /* in the case of slip, we are now priviliged */
  294.  
  295.     /*
  296.      * Hardwired connections require the
  297.      *  line speed set before they make any transmissions
  298.      *  (this is particularly true of things like a DF03-AC)
  299.      */
  300.     if(HW)
  301.         ttysetup(i);
  302.     if(p = lconnect())
  303.     {
  304.         printf("\07%s\n[EOT]\n",p);
  305.         daemon_uid();
  306.         (void)uu_unlock(uucplock);
  307.         exit(1);
  308.     }
  309.     if(!HW)
  310.         ttysetup(i);
  311.  
  312.  
  313.     if(LS != NOSTR)
  314.     {
  315.         fprintf(stderr,"\07[Logging in...]\r\n");
  316.         if(p = login())
  317.         {
  318.             printf("\07%s\n[EOT]\n",p);
  319.             daemon_uid();
  320.             (void)uu_unlock(uucplock);
  321.             exit(1);
  322.         }
  323.     }
  324.  
  325.     if(page)
  326.     {
  327.         i = sendpage(data);
  328.         daemon_uid();
  329.         (void)uu_unlock(uucplock);
  330.         exit(i);
  331.     }
  332.  
  333.     if(slip)
  334.     {
  335.         i = runslip();
  336.         daemon_uid();
  337.         (void)uu_unlock(uucplock);
  338.         exit(i);
  339.     }
  340.  
  341. cucommon:
  342.     /*
  343.      * From here down the code is shared with
  344.      * the "cu" version of tip.
  345.      */
  346.  
  347.     ioctl(0,TIOCGETP,(char *)&defarg);
  348.     ioctl(0,TIOCGETC,(char *)&defchars);
  349.     ioctl(0,TIOCGLTC,(char *)&deflchars);
  350.     ioctl(0,TIOCGETD,(char *)&odisc);
  351.     arg = defarg;
  352. #ifdef TIPX
  353.     arg.sg_flags = CBREAK;
  354. #else
  355.     arg.sg_flags = ANYP | CBREAK;
  356. #endif
  357.     tchars = defchars;
  358.     tchars.t_intrc = tchars.t_quitc = -1;
  359.     ltchars = deflchars;
  360.     ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc
  361.         = ltchars.t_lnextc = -1;
  362.     raw();
  363.  
  364.     pipe(fildes);
  365.     pipe(repdes);
  366.     signal(SIGALRM,timeout);
  367.  
  368.     /*
  369.      * Everything's set up now:
  370.      *    connection established (hardwired or dialup)
  371.      *    line conditioned (baud rate, mode, etc.)
  372.      *    internal data structures (variables)
  373.      * so, fork one process for local side and one for remote.
  374.      */
  375. #ifdef TIPX
  376.     printf("tipx (tip 4.3 mod by wht@n4hgf %s.%02d) connected to %s\r\n",
  377.         tipx_rev,PATCHLEVEL,opened_tty);
  378.     fputs("Copyright (c) 1983 The Regents of the University of California.\r\n",
  379.         stdout);
  380.     printf("line speed = %s, tandem = %s\r\n",
  381.         B_to_baud_rate(ttyarg.sg_ospeed),
  382.         (ttyarg.sg_flags & TANDEM) ? "yes" : "no");
  383. #else
  384.     printf(cumode ? "Connected\r\n" : "\07connected\r\n");
  385. #endif
  386.     if(pid = fork())
  387.         tipin();
  388.     else
  389.         tipout();
  390.     /*NOTREACHED*/
  391. }
  392.  
  393. sigfunc_t
  394. cleanup()
  395. {
  396.  
  397.     daemon_uid();
  398.     (void)uu_unlock(uucplock);
  399.     if(pid)
  400.     {
  401.         (void) kill(pid,SIGTERM);
  402.         unraw();
  403.     }
  404.     else if(odisc)
  405.         ioctl(0,TIOCSETD,(char *)&odisc);
  406.     exit(0);
  407. }
  408.  
  409. /*
  410.  * Muck with user ID's.  We are setuid to the owner of the lock
  411.  * directory when we start.  user_uid() reverses real and effective
  412.  * ID's after startup, to run with the user's permissions.
  413.  * daemon_uid() switches back to the privileged uid for unlocking.
  414.  * Finally, to avoid running a shell with the wrong real uid,
  415.  * shell_uid() sets real and effective uid's to the user's real ID.
  416.  */
  417. static int uidswapped;
  418.  
  419. user_uid()
  420. {
  421.     if(uidswapped == 0)
  422.     {
  423.         setregid(egid,gid);
  424.         setreuid(euid,uid);
  425.         uidswapped = 1;
  426.     }
  427. }
  428.  
  429. daemon_uid()
  430. {
  431.     if(uidswapped)
  432.     {
  433.         setreuid(uid,euid);
  434.         setregid(gid,egid);
  435.         uidswapped = 0;
  436.     }
  437. }
  438.  
  439. shell_uid()
  440. {
  441.  
  442.     setreuid(uid,uid);
  443.     setregid(gid,gid);
  444. }
  445.  
  446. /*
  447.  * put the controlling keyboard into raw mode
  448.  */
  449. raw()
  450. {
  451.  
  452.     ioctl(0,TIOCSETP,&arg);
  453.     ioctl(0,TIOCSETC,&tchars);
  454.     ioctl(0,TIOCSLTC,<chars);
  455.     ioctl(0,TIOCSETD,(char *)&disc);
  456. }
  457.  
  458.  
  459. /*
  460.  * return keyboard to normal mode
  461.  */
  462. unraw()
  463. {
  464.  
  465.     ioctl(0,TIOCSETD,(char *)&odisc);
  466.     ioctl(0,TIOCSETP,(char *)&defarg);
  467.     ioctl(0,TIOCSETC,(char *)&defchars);
  468.     ioctl(0,TIOCSLTC,(char *)&deflchars);
  469. }
  470.  
  471. static jmp_buf promptbuf;
  472.  
  473. /*
  474.  * Print string ``s'', then read a string
  475.  *  in from the terminal.  Handles signals & allows use of
  476.  *  normal erase and kill characters.
  477.  */
  478. prompt(s,p)
  479. char *s;
  480. register char *p;
  481. {
  482.     register char *b = p;
  483.     sigfunc_t(*oint)(),(*oquit)();
  484.  
  485.     stoprompt = 0;
  486.     oint = signal(SIGINT,intprompt);
  487.     oquit = signal(SIGQUIT,SIG_IGN);
  488.     unraw();
  489.     printf("%s",s);
  490.     if(setjmp(promptbuf) == 0)
  491.         while((*p = getchar()) != EOF && *p != '\n')
  492.             p++;
  493.     *p = '\0';
  494.  
  495.     raw();
  496.     signal(SIGINT,oint);
  497.     signal(SIGQUIT,oint);
  498.     return(stoprompt || p == b);
  499. }
  500.  
  501. /*
  502.  * Interrupt service routine during prompting
  503.  */
  504. sigfunc_t
  505. intprompt()
  506. {
  507.  
  508.     signal(SIGINT,SIG_IGN);
  509.     stoprompt = 1;
  510.     printf("\r\n");
  511.     longjmp(promptbuf,1);
  512. }
  513.  
  514. /*
  515.  * ****TIPIN   TIPIN****
  516.  */
  517. tipin()
  518. {
  519.     char gch,bol = 1;
  520.  
  521.     /*
  522.      * Kinda klugey here...
  523.      *   check for scripting being turned on from the .tiprc file,
  524.      *   but be careful about just using setscript(), as we may
  525.      *   send a SIGEMT before tipout has a chance to set up catching
  526.      *   it; so wait a second, then setscript()
  527.      */
  528.     if(boolean(value(SCRIPT)))
  529.     {
  530.         sleep(1);
  531.         setscript();
  532.     }
  533.  
  534. #ifdef TIPX
  535.     if(!rawthru)
  536.         goto NORMAL_TIP2;
  537.  
  538. RAWTHRU_TIP:
  539.     printf(rawthru_msg);
  540.     while(1)
  541.     {
  542.         long count;
  543.         char chbuf[4];
  544.         read(0,&gch,1);
  545.         if((gch == character(value(ESCAPE))))
  546.         {
  547.             sleep(1);
  548.             ioctl(0,FIONREAD,&count);
  549.             if(count == 2)
  550.             {    /* might have raw mode escape */
  551.                 read(0,chbuf,2);
  552.                 if((chbuf[0] == character(value(ESCAPE))) &&
  553.                     (chbuf[1] == character(value(ESCAPE))))
  554.                 {
  555.                     printf("rawthru%s",ctrl(chbuf[0]));
  556.                     if(!(gch = escape()))
  557.                     {
  558.                         if(!rawthru)
  559.                         {
  560.                             bol = 1;
  561.                             goto NORMAL_TIP;
  562.                         }
  563.                         continue;
  564.                     }
  565.                 }
  566.                 else
  567.                 {
  568.                     gch = character(value(ESCAPE));
  569.                     write(FD,&gch,1);
  570.                     write(FD,chbuf,2);
  571.                     continue;
  572.                 }
  573.             }
  574.         }
  575.         write(FD,&gch,1);
  576.     }
  577.  
  578. NORMAL_TIP:
  579.     printf(no_rawthru_msg);
  580. NORMAL_TIP2:
  581. #endif /* TIPX */
  582.     while(1)
  583.     {
  584.         gch = getchar()&0177;
  585.         if((gch == character(value(ESCAPE))) && bol)
  586.         {
  587.             if(!(gch = escape()))
  588. #ifdef TIPX
  589.             {
  590.                 if(rawthru)
  591.                     goto RAWTHRU_TIP;
  592.                 continue;
  593.             }
  594. #else /* TIPX */
  595.             continue;
  596. #endif /* TIPX */
  597.         }
  598.         else if(!cumode && gch == character(value(RAISECHAR)))
  599.         {
  600.             boolean(value(RAISE)) = !boolean(value(RAISE));
  601.             continue;
  602.         }
  603.         else if(gch == '\r')
  604.         {
  605.             bol = 1;
  606.             pwrite(FD,&gch,1);
  607.             if(boolean(value(HALFDUPLEX)))
  608.                 printf("\r\n");
  609.             continue;
  610.         }
  611.         else if(!cumode && gch == character(value(FORCE)))
  612.             gch = getchar()&0177;
  613.         bol = any(gch,value(EOL));
  614.         if(boolean(value(RAISE)) && islower(gch))
  615.             gch = toupper(gch);
  616.         pwrite(FD,&gch,1);
  617.         if(boolean(value(HALFDUPLEX)))
  618.             printf("%c",gch);
  619.     }
  620. }
  621.  
  622. /*
  623.  * Escape handler --
  624.  *  called on recognition of ``escapec'' at the beginning of a line
  625.  */
  626. escape()
  627. {
  628.     register char gch;
  629.     register esctable_t *p;
  630.     char c = character(value(ESCAPE));
  631.     extern esctable_t etable[];
  632.  
  633.     gch = (getchar()&0177);
  634.     for(p = etable; p->e_char; p++)
  635.         if(p->e_char == gch)
  636.         {
  637.             if((p->e_flags&PRIV) && uid)
  638.                 continue;
  639. #ifdef TIPX
  640.             if(!rawthru)
  641. #endif
  642.                 printf("%s",ctrl(c));
  643.             (*p->e_func)(gch);
  644.             return(0);
  645.         }
  646.     /* ESCAPE ESCAPE forces ESCAPE */
  647.     if(c != gch)
  648.         pwrite(FD,&c,1);
  649.     return(gch);
  650. }
  651.  
  652. speed(n)
  653. int n;
  654. {
  655.     register int *p;
  656.  
  657.     for(p = bauds; *p != -1;  p++)
  658.         if(*p == n)
  659.             return(p - bauds);
  660.     return(NULL);
  661. }
  662.  
  663. any(c,p)
  664. register char c,*p;
  665. {
  666.     while(p && *p)
  667.         if(*p++ == c)
  668.             return(1);
  669.     return(0);
  670. }
  671.  
  672. size(s)
  673. register char *s;
  674. {
  675.     register int i = 0;
  676.  
  677.     while(s && *s++)
  678.         i++;
  679.     return(i);
  680. }
  681.  
  682. char *
  683. interp(s)
  684. register char *s;
  685. {
  686.     static char buf[256];
  687.     register char *p = buf,c,*q;
  688.  
  689.     while(c = *s++)
  690.     {
  691.         for(q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
  692.             if(*q++ == c)
  693.             {
  694.                 *p++ = '\\';
  695.                 *p++ = *q;
  696.                 goto next;
  697.             }
  698.         if(c < 040)
  699.         {
  700.             *p++ = '^';
  701.             *p++ = c + 'A'-1;
  702.         }
  703.         else if(c == 0177)
  704.         {
  705.             *p++ = '^';
  706.             *p++ = '?';
  707.         }
  708.         else
  709.             *p++ = c;
  710. next:
  711.         ;
  712.     }
  713.     *p = '\0';
  714.     return(buf);
  715. }
  716.  
  717. char *
  718. ctrl(c)
  719. char c;
  720. {
  721.     static char s[3];
  722.  
  723.     if(c < 040 || c == 0177)
  724.     {
  725.         s[0] = '^';
  726.         s[1] = c == 0177 ? '?' : c+'A'-1;
  727.         s[2] = '\0';
  728.     }
  729.     else 
  730.     {
  731.         s[0] = c;
  732.         s[1] = '\0';
  733.     }
  734.     return(s);
  735. }
  736.  
  737. /*
  738.  * Help command
  739.  */
  740. help(c)
  741. char c;
  742. {
  743.     register esctable_t *p;
  744.     extern esctable_t etable[];
  745.  
  746.     printf("%c\r\n",c);
  747.     for(p = etable; p->e_char; p++)
  748.     {
  749.         if((p->e_flags&PRIV) && uid)
  750.             continue;
  751.         printf("%2s",ctrl(character(value(ESCAPE))));
  752.         printf("%-2s %c   %s\r\n",ctrl(p->e_char),
  753.             p->e_flags&EXP ? '*': ' ',p->e_help);
  754.     }
  755. }
  756.  
  757. /*
  758.  * Set up the "remote" tty's state
  759.  */
  760. ttysetup(speed)
  761. int speed;
  762. {
  763.     unsigned bits = LDECCTQ;
  764.  
  765.     ttyarg.sg_ispeed = ttyarg.sg_ospeed = speed;
  766.     ttyarg.sg_flags = RAW;
  767.     if(boolean(value(TAND)))
  768.         ttyarg.sg_flags |= TANDEM;
  769.     if(boolean(value(DTRHUP)))
  770.     {
  771.         ioctl(FD,TIOCSDTR,0);
  772.         ioctl(FD,TIOCHPCL,0);
  773.     }
  774.     ioctl(FD,TIOCSETP,(char *)&ttyarg);
  775.     ioctl(FD,TIOCLBIS,(char *)&bits);
  776. }
  777.  
  778. /*
  779.  * Return "simple" name from a file name,
  780.  * strip leading directories.
  781.  */
  782. char *
  783. sname(s)
  784. register char *s;
  785. {
  786.     register char *p = s;
  787.  
  788.     while(*s)
  789.         if(*s++ == '/')
  790.             p = s;
  791.     return(p);
  792. }
  793.  
  794. static char partab[0200];
  795.  
  796. /*
  797.  * Do a write to the remote machine with the correct parity.
  798.  * We are doing 8 bit wide output, so we just generate a character
  799.  * with the right parity and output it.
  800.  */
  801. pwrite(fd,buf,n)
  802. int fd;
  803. char *buf;
  804. register int n;
  805. {
  806.     register int i;
  807.     register char *bp;
  808.     extern int errno;
  809. #ifdef TIPX
  810.     extern int rawthru;
  811.  
  812.     if(rawthru)
  813.     {
  814.         write(fd,buf,n);
  815.         return;
  816.     }
  817. #endif /* TIPX */
  818.  
  819.     bp = buf;
  820.     for(i = 0; i < n; i++)
  821.     {
  822.         *bp = partab[(*bp) & 0177];
  823.         bp++;
  824.     }
  825.     if(write(fd,buf,n) < 0)
  826.     {
  827.         if(errno == EIO)
  828.             abort("Lost carrier.");
  829.         /* this is questionable */
  830.         perror("write");
  831.     }
  832. }
  833.  
  834. /*
  835.  * Build a parity table with appropriate high-order bit.
  836.  */
  837. setparity(defparity)
  838. char *defparity;
  839. {
  840.     register int i;
  841.     char *parity;
  842.     extern char evenpartab[];
  843.  
  844.     if(value(PARITY) == NOSTR)
  845.         value(PARITY) = defparity;
  846.     parity = value(PARITY);
  847.     for(i = 0; i < 0200; i++)
  848.         partab[i] = evenpartab[i];
  849.     if(equal(parity,"even"))
  850.         return;
  851.     if(equal(parity,"odd"))
  852.     {
  853.         for(i = 0; i < 0200; i++)
  854.             partab[i] ^= 0200;    /* reverse bit 7 */
  855.         return;
  856.     }
  857.     if(equal(parity,"none") || equal(parity,"zero"))
  858.     {
  859.         for(i = 0; i < 0200; i++)
  860.             partab[i] &= ~0200;    /* turn off bit 7 */
  861.         return;
  862.     }
  863.     if(equal(parity,"one"))
  864.     {
  865.         for(i = 0; i < 0200; i++)
  866.             partab[i] |= 0200;    /* turn on bit 7 */
  867.         return;
  868.     }
  869.     fprintf(stderr,"%s: unknown parity value\n",PA);
  870.     fflush(stderr);
  871. }
  872.  
  873. /* The uid could be determined by stat()-ing ACULOG */
  874. getuucpuid()
  875. {
  876.     struct passwd *pw;
  877.  
  878.     if((pw = getpwnam("uucp")) == NULL)
  879.     {
  880.         fprintf(stderr,"tip: unable to get uucp uid\n");
  881.         exit(1);
  882.     }
  883.     return(pw->pw_uid);
  884. }
  885.